﻿using HuaCheng.DataAccess;
using HuaCheng.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace HuaCheng.Controller
{
    public class AutoConControl
    {
        static CommandProtocol.Broadcast broadData = new CommandProtocol.Broadcast();
        static CommandProtocol.DeviceConfig configData = new CommandProtocol.DeviceConfig();
        /// <summary>
        /// 发送广播包
        /// </summary>
        public static void BeginBroadcast()
        {
            try
            {
                //先监听反馈包，再开始广播，以免遗漏反馈包
                BeginReceive();
                //实例化一个udp的Socket           
                Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
                ProtocolType.Udp);
                //设置ip为255.255.255.255，目标的接收端口号为5003
                IPEndPoint iep1 = new IPEndPoint(IPAddress.Broadcast, 5003);               
                sock.SetSocketOption(SocketOptionLevel.Socket,
                SocketOptionName.Broadcast, 1);
                //组装广播包数据
                byte[] data = broadData.Command();                
                //发送广播包
                sock.SendTo(data, iep1);                              
                sock.Close();               
            }
            catch(Exception e)
            {
                Console.WriteLine(e.StackTrace + e.Message);
            }
        }
        /// <summary>
        /// 接收反馈包
        /// </summary>
        public static void BeginReceive()
        {
            IPEndPoint ip = new IPEndPoint(IPAddress.Parse(IndexPageControl.GetClientLocalIPv4Address()), 5004);
            Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            newsock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            newsock.Bind(ip);
            Thread thread = new Thread(new ParameterizedThreadStart(ReceiveFeedBack));
            thread.IsBackground = true;
            thread.Start(newsock);
        }
        /// <summary>
        /// 循环接收反馈包
        /// </summary>
        /// <param name="obj"></param>
        public static void ReceiveFeedBack(object obj)
        {
            Socket newsock = (Socket)obj;
            while (true)
            {
                byte[] buffer = new byte[1024];
                int len = 0;
                IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 5004);
                EndPoint Remote = (EndPoint)remoteEP;

                len = newsock.ReceiveFrom(buffer, ref Remote);
                if (len == 34)
                {
                    DeviceInfo device = ChannelStateControl.byte2DeviceInfo(buffer, 32);
                    string[] str = Remote.ToString().Split(':');
                    bool isBelonged = DeviceHelper.UpdateIpByMac(str[0], device.DeviceMac, device.DeviceId);
                    if (isBelonged)
                    {
                        configData = DeviceHelper.GetConfigByIp(str[0], configData);
                        byte[] sendData = configData.Command();
                        IPEndPoint iep = new IPEndPoint(IPAddress.Parse(str[0]), 5003);
                        EndPoint sep = (EndPoint)iep;
                        newsock.BeginSendTo(sendData, 0, sendData.Length, SocketFlags.None, sep, new AsyncCallback(SendDataEnd), newsock);
                    }
                }
            }
        }
        ///// <summary>
        ///// 接受方法的回调函数
        ///// </summary>
        ///// <param name="ar"></param>
        //private static void HandleDataReceived(IAsyncResult ar)
        //{
        //    AsyncSocketState asyState = (AsyncSocketState)ar.AsyncState;
        //    Socket sock = asyState.ClientSocket;
        //    EndPoint ep = asyState.remote;
        //    if (!isReceiveOver)
        //    {
        //        try
        //        {
        //            //接收数据
        //            byte[] data = new byte[1024];
        //            int recv = sock.ReceiveFrom(data, ref ep);
        //            //解析数据,更新设备表中MacId和设备ID匹配的设备的ip
        //            if (recv == 34)
        //            {
        //                DeviceInfo device = ChannelStateControl.byte2DeviceInfo(data, 32);
        //                string[] str = ep.ToString().Split(':');
        //                DeviceHelper.UpdateIpByMac(str[0], device.DeviceMac, device.DeviceId);
        //                try
        //                {
        //                    configData = DeviceHelper.GetConfigByIp(str[0], configData);
        //                    byte[] sendData = configData.Command();
        //                    IPEndPoint iep = new IPEndPoint(IPAddress.Parse(str[0]), 5003);
        //                    EndPoint sep = (EndPoint)iep;
        //                    sock.BeginSendTo(sendData, 0, sendData.Length, SocketFlags.None, sep, new AsyncCallback(SendDataEnd), sock);
        //                }
        //                catch (Exception e)
        //                {
        //                    Console.WriteLine(e.StackTrace + e.Message);
        //                }
        //            }

        //        }
        //        catch (Exception e)
        //        {
        //            Console.WriteLine(e.StackTrace + e.Message);
        //        }
        //        finally
        //        {
        //            if (!isReceiveOver)
        //            {
        //                try
        //                {
        //                    sock.BeginReceiveFrom(asyState.RecvDataBuffer, 0, asyState.RecvDataBuffer.Length, SocketFlags.None, ref ep, new AsyncCallback(HandleDataReceived), asyState);
        //                }
        //                catch (Exception e)
        //                {
        //                    Console.WriteLine(e.StackTrace + e.Message);
        //                }
        //            }
        //        }
        //    }
        //}
        /// <summary>
        /// 发送方法的回调函数
        /// </summary>
        /// <param name="ar"></param>
        private static void SendDataEnd(IAsyncResult ar)
        {
            ((Socket)ar.AsyncState).EndSendTo(ar);
        }

    }
}
